package com.yqd.lesson.actor.nine

//#persistent-actor-example
import akka.actor._
import akka.persistence._

case class Cmd(data: String)
case class Evt(data: String)

case class ExampleState(events: List[String] = Nil) {
  def updated(evt: Evt): ExampleState = copy(evt.data :: events)
  def size: Int = events.length
  override def toString: String = events.reverse.toString
}

class ExamplePersistentActor extends PersistentActor with ActorLogging {
  override def persistenceId = "sample-id-12"

  var state = ExampleState()

  def updateState(event: Evt): Unit =
    state = state.updated(event)

  def numEvents =
    state.size

  val receiveRecover: Receive = {
    case evt: Evt => {
      println(s"恢复：$evt")
      updateState(evt)
    }
    case SnapshotOffer(_, snapshot: ExampleState) => {
      println(s"快照是：$snapshot")
      state = snapshot
    }
  }

  val receiveCommand: Receive = {
    case Cmd(data) =>
      persist(Evt(s"${data}-${numEvents}"))(updateState)
      persist(Evt(s"${data}-${numEvents + 1}")) { event =>
        updateState(event)
        context.system.eventStream.publish(event)
      }
    case "snap"  => saveSnapshot(state)
    case "print" => println(state)
    case "exception" =>
      throw new Exception;
  }

}
//#persistent-actor-example

object PersistentActorExample extends App {

  val system = ActorSystem("example")
  val persistentActor = system.actorOf(Props[ExamplePersistentActor], "persistentActor-4-scala")

  persistentActor ! Cmd("a")
  persistentActor ! Cmd("b")
  persistentActor ! Cmd("c")
  persistentActor ! "snap"
  persistentActor ! Cmd("d")
  Thread.sleep(1000)
  persistentActor ! "exception"
  persistentActor ! Cmd("e")
  persistentActor ! Cmd("f")
  persistentActor ! "print"

  Thread.sleep(10000)
  system.terminate()
}
